#!/usr/bin/python3
# -*- coding: utf-8 -*-
# coding=utf-8
# Author: BillySir
from __future__ import print_function
import sys
from rule import *
from chess_board import *
from dimension import T2D

# print_process = True  # 是否打印解题（试填）过程
print_process = False  # 是否打印解题（试填）过程


class UniqueRule(Rule):
    """不重复规则"""

    def __init__(self, basket: ChessBasket):
        super(UniqueRule, self).__init__(basket)

    def validate(self):
        data = {1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0, 7: 0, 8: 0, 9: 0, }
        for cell in self.parents:
            if cell.chess is None:
                continue
            if data[cell.chess.value] > 0:
                return False
            data[cell.chess.value] = 1
        return True

    def can_fill(self, chess_list, parent: Cell):
        """获取可下的棋子集合与给定的chess_list的交集"""
        if parent.chess is not None:
            raise Exception("parent.chess is not None:" + parent.chess)

        data = {1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0, 7: 0, 8: 0, 9: 0, }
        for cell in self.parents:
            if cell.chess is None:
                continue
            if data[cell.chess.value] > 0:
                raise Exception("found duplicate value in range. rule:%d, value:%d" % (self.index, cell.chess.value))
            data[cell.chess.value] = 1
        return [chess for chess in chess_list if data[chess.value] == 0]

    def __str__(self):
        return "rule[%d]" % self.index

    __repr__ = __str__


def run():
    """数独"""

    # 初始化棋子
    chess_list = [Chess(v + 1, v + 1) for v in range(9)]
    # 初始化棋盒
    chess_dist = {}
    for chess in chess_list:
        chess_dist[chess] = 9  # 每个数字可以用9次
    # print('chess_dist:' + str(chess_dist))
    basket = ChessBasket(chess_dist)

    # 初始化棋盘上的格子
    cells = [Cell(basket) for _ in range(81)]
    # 初始化规则
    rules = [UniqueRule(basket) for _ in range(9 * 3)]

    # 初始化棋盘
    board = ChessBoard(cells)
    board.rules = rules
    board.print_process = print_process
    board.width = 9
    board.height = 9

    T2D.board = board
    T2D.width = 9
    T2D.height = 9

    Rule.batch_bind_parents(rules[0:9], T2D.get_cells_list("-"))
    Rule.batch_bind_parents(rules[9:18], T2D.get_cells_list("|"))
    Rule.batch_bind_parents(rules[18:27], T2D.get_cells_list((3, 3)))

    # 放固定棋子
    _ = None
    known = [
        _, _, 8, _, _, _, 2, _, _,
        _, 3, _, 8, _, 2, _, 6, _,
        7, _, _, _, 9, _, _, _, 5,
        _, 5, _, _, _, _, _, 1, _,
        _, _, 4, _, _, _, 6, _, _,
        _, 2, _, _, _, _, _, 7, _,
        4, _, _, _, 8, _, _, _, 6,
        _, 7, _, 1, _, 3, _, 9, _,
        _, _, 1, _, _, _, 8, _, _,
    ]
    known = [
        8, 1, _, _, _, 3, 2, 9, _,
        _, 6, 7, _, _, _, _, _, _,
        9, _, _, 5, _, _, _, _, 6,
        _, _, _, 4, _, 8, _, _, _,
        6, _, 4, _, _, _, 8, _, 9,
        _, _, _, 2, _, 9, _, _, _,
        7, _, _, _, _, 1, _, _, 8,
        _, _, _, _, _, _, 3, 7, _,
        _, 5, 3, 8, _, _, _, 4, 2,
    ]
    # known = [
    #     _, 4, _, _, 6, _, _, _, 7,
    #     _, _, 9, _, 5, _, _, _, _,
    #     _, _, 3, 8, _, _, _, _, 9,
    #     _, 5, _, _, _, 8, 1, _, 6,
    #     9, _, _, _, _, _, _, _, 4,
    #     8, _, 2, 6, _, _, _, 5, _,
    #     2, _, _, _, _, 7, 4, _, _,
    #     _, _, _, _, 1, _, 7, _, _,
    #     7, _, _, _, 8, _, _, 3, _,
    # ]
    for i in range(len(known)):
        value = known[i]
        if value is not None:
            chess = basket.get_chess_by_value(value)
            board.put_chess(i, chess[0])

    # 启动求解
    board.guess()
    print("finished")
    print("guess count: %d" % basket.guess_count)
